package ws

import (
	"encoding/json"
	"errors"
	"fmt"
	"log"

	"github.com/google/uuid"
	"github.com/gorilla/websocket"
	"github.com/smash-llj/Nexa-server/global"
	"github.com/smash-llj/Nexa-server/models"
	"gorm.io/gorm"
)

type Client struct {
	ID      int
	Hub     *Hub
	Conn    *websocket.Conn
	Message chan *Message
}

type HeartBeatResponse struct {
	MessageType int    `json:"messageType"` //消息类型
	Content     string `json:"content"`
}

type UserInfo struct {
	Name   string `json:"name"`
	Avatar string `json:"avatar"`
}

type GroupInfo struct {
	Name   string `json:"name"`
	Avatar string `json:"avatar"`
}

type Message struct {
	UUId        string    `json:"uuid"`
	SendId      int       `json:"sendId"`      // 发送者id
	ToId        int       `json:"toId"`        // 接受者id
	SessionId   string    `json:"sessionId"`   //会话Id
	QuotationId string    `json:"quotationId"` // 引用消息id
	Content     string    `json:"content"`
	FileSize    int       `json:"fileSize"`
	FileName    string    `json:"fileName"`
	FileUrl     string    `json:"fileUrl"`
	LocalPath   string    `json:"localPath"`   //文件本地地址
	ChatType    int       `json:"chatType"`    //聊天类型 单聊/群聊
	MessageType int       `json:"messageType"` //消息类型
	CallType    int       `json:"callType"`    // 呼叫类型 语音还是视频
	CallStatus  int       `json:"callStatus"`  //呼叫状态 0->wait 1->agree 2->reject 3->超时
	UserInfo    UserInfo  `json:"userInfo"`
	GroupInfo   GroupInfo `json:"groupInfo"`
}

func (c *Client) ReadMessage() {
	defer c.Conn.Close() // 简化 defer 语法
	for {
		msg := &Message{}
		_, message, err := c.Conn.ReadMessage()
		if err != nil {
			if websocket.IsCloseError(err, websocket.CloseNoStatusReceived, websocket.CloseGoingAway) {
				fmt.Println("连接已关闭:", err)
			} else {
				fmt.Println("读取消息时发生错误:", err)
			}
			break
		}
		if json.Unmarshal(message, msg) != nil {
			log.Println("解析消息失败:", err)
			break
		}
		fmt.Println("接受到了消息:", msg)
		if c.checkMessageType(*msg) {
			c.Hub.Broadcast <- msg
		}
	}
}

func (c *Client) WriteMessage() {
	defer func(Conn *websocket.Conn) {
		_ = Conn.Close()
	}(c.Conn)
	for {
		message, ok := <-c.Message
		if !ok {
			log.Print("读取消息失败")
			return
		}
		err := c.Conn.WriteJSON(message)
		log.Println("接受到了消息", message)
		if err != nil {
			log.Print("发送消息失败", err)
			return
		}
	}
}

// CheckMessageType 判断消息类型
func (c *Client) checkMessageType(message Message) bool {
	switch message.MessageType {
	case global.MessageText, global.MessageImage, global.MessageFile, global.MessageMixTxtImg:
		if createMessageRecord(message) != nil || handelSessionMessage(message) != nil {
			return false
		}
		return true
	case global.MessageHeart:
		//如果是心跳类型 直接回复
		_ = c.Conn.WriteJSON(&HeartBeatResponse{
			MessageType: global.MessageHeart,
			Content:     "ok",
		})
		return false
	case global.MessageRequestAdd:
		//前端先通过api添加请求记录 后发送ws消息通知对方 然后更新对方session
		// 好友请求 只更新对方session
		return createFriendRequestSession(message)
	//	如果是视频或者语音之类的直接传递 不需要处理
	case global.MessageRtc:
		return true
	default:
		fmt.Println("未知的消息类型:", message.MessageType)
		return false
	}
}

// 存储消息记录
func createMessageRecord(message Message) error {
	data := models.Message{
		UUId:        message.UUId,
		SendId:      message.SendId,
		ToId:        message.ToId,
		QuotationId: message.QuotationId,
		SessionId:   message.SessionId,
		Content:     message.Content,
		ChatType:    message.ChatType,
		CallType:    message.CallType,
		MessageType: message.MessageType,
		FileSize:    message.FileSize,
		FileName:    message.FileName,
		FileUrl:     message.FileUrl,
		CallStatus:  message.CallStatus,
	}
	return global.DB.Create(&data).Error
}

// 处理session消息=>判断是群还是好友聊天
func handelSessionMessage(message Message) error {
	if message.ChatType == global.ChatTypeGroup {
		return updateGroupSession(message)
	}
	return updateBothSessions(message, message.SendId, message.ToId)
}

// 更新双方session
func updateBothSessions(message Message, senderId, receiverId int) error {
	return global.DB.Transaction(func(tx *gorm.DB) error {
		if err := updateSession(tx, message, senderId, receiverId, true); err != nil {
			return err
		}
		return updateSession(tx, message, receiverId, senderId, false)
	})
}

func updateSession(tx *gorm.DB, message Message, userId, friendId int, isSender bool) error {
	// 尝试查找或创建会话
	session := models.Session{
		SessionId: message.SessionId,
		UserId:    userId,
	}
	if err := tx.Where(session).FirstOrCreate(&session).Error; err != nil {
		return err
	}
	// 构建更新字段
	updates := map[string]interface{}{
		"session_type": message.MessageType,
		"last_msg":     message.Content,
		"to_id":        friendId,
		"chat_type":    message.ChatType,
	}
	if isSender {
		updates["unread"] = 0
	} else {
		updates["unread"] = gorm.Expr("unread + 1")
	}
	// 更新会话
	return tx.Model(&session).Updates(updates).Error
}

// 更新群session
// 查询群成员 给每个群成员 添加session
func updateGroupSession(message Message) error {
	db := global.DB
	memberIDs, err := GetGroupMemberList(message.ToId)
	if err != nil {
		return err
	}
	return db.Transaction(func(tx *gorm.DB) error {
		// 一次性查询所有成员的会话存在情况
		var existingSessions []models.Session
		if err := tx.Model(&models.Session{}).
			Where("session_id = ? AND user_id IN ?", message.SessionId, memberIDs).
			Find(&existingSessions).Error; err != nil {
			return err
		}
		existingMap := make(map[int]bool)
		var updateUserIDs []int
		for _, session := range existingSessions {
			existingMap[session.UserId] = true
			updateUserIDs = append(updateUserIDs, session.UserId)
		}

		if len(updateUserIDs) > 0 {
			if err := tx.Model(&models.Session{}).
				Where("session_id = ? AND user_id IN ?", message.SessionId, updateUserIDs).
				Updates(map[string]interface{}{
					"last_msg":     message.Content,
					"chat_type":    message.ChatType,
					"session_type": message.MessageType,
					"unread":       gorm.Expr("CASE WHEN user_id = ? THEN unread ELSE unread + 1 END", message.SendId),
				}).Error; err != nil {
				return err
			}
		}

		var newSessions []models.Session
		for _, member := range memberIDs {
			if !existingMap[member] {
				unread := 1
				if member == message.SendId {
					unread = 0
				}
				newSessions = append(newSessions, models.Session{
					UserId:      member,
					ToId:        message.ToId,
					SessionId:   message.SessionId,
					ChatType:    global.ChatTypeGroup,
					SessionType: message.MessageType,
					LastMsg:     message.Content,
					Unread:      unread,
				})
			}
		}

		if len(newSessions) > 0 {
			if err := tx.Create(&newSessions).Error; err != nil {
				return err
			}
		}
		return nil
	})
}

// 创建被添加方session
func createFriendRequestSession(message Message) bool {
	var session models.Session
	lastMsg := fmt.Sprintf("%s请求添加为好友", message.UserInfo.Name)
	err := global.DB.
		Model(&models.Session{}).
		Select("id").
		Where("session_type = ?", message.MessageType).
		First(&session).Error

	if err == nil {
		err = global.DB.Model(&session).Updates(map[string]interface{}{
			"last_msg": lastMsg,
			"unread":   gorm.Expr("unread + ?", 1),
		}).Error
		if err != nil {
			fmt.Println("更新好友请求 session 失败:", err)
			return false
		}
	} else if errors.Is(err, gorm.ErrRecordNotFound) {
		err = global.DB.Create(&models.Session{
			SessionId:   uuid.New().String(),
			UserId:      message.ToId,
			ToId:        message.SendId,
			LastMsg:     lastMsg,
			ChatType:    message.ChatType,
			SessionType: message.MessageType,
			Unread:      1,
		}).Error
		if err != nil {
			fmt.Println("创建好友请求 session 失败:", err)
			return false
		}
	} else {
		fmt.Println("查询好友请求 session 失败:", err)
		return false
	}
	return true
}

// GetGroupMemberList 查询群成员
func GetGroupMemberList(groupId int) ([]int, error) {
	var memberIDs []int
	db := global.DB

	err := db.
		Table("group_member").
		Select("user_id").
		Where("group_id = ?", groupId).
		Scan(&memberIDs).Error

	if err != nil {
		return nil, err
	}
	return memberIDs, nil
}
